#pragma once

#include "Vector.h"

class Matrix
{
public:
	Matrix ( size_t rowsCount, size_t columnsCount);
	Matrix ( size_t rowsCount, size_t columnsCount, const Vector* vector);
	Matrix ( size_t rowsCount, size_t columnsCount, const double *data );
	Matrix ( size_t rowsCount, size_t columnsCount, const Matrix& another);
	Matrix ( const Matrix &another);
	~Matrix ();
	
	size_t getColumnsCount() const;
	size_t getRowsCount() const;
	Vector column(size_t columnIndex) const;
	Matrix transpose() const;
	double determinant() const;
	Matrix inverse() const;
	Matrix roundToZero() const;

	const Vector& operator [] ( size_t index) const;
	Vector& operator [] ( size_t index);
	Matrix& operator = (const Matrix& another);
	Vector solveLinearEquation (const Vector& freeTermsVector);
	void exchangeRows(size_t firstRow, size_t secondRow);
	void exchangeColumns(size_t firstColumn, size_t secondColumn);
	
	Vector operator* (const Vector& vector) const;
	Matrix operator* (double constant) const;
	Matrix operator* (const Matrix& second) const;
	Matrix operator+(const Matrix& secondMatrix) const;
	Matrix operator-(const Matrix& secondMatrix) const;
		
private:
	bool isValidRow(size_t row) const;
	bool isValidColumn(size_t column) const;

private:
	Vector **rows;
	size_t rowsCount;
	size_t columnsCount;
};

Matrix operator* (double constant, const Matrix& another );
Vector operator*(const Vector& vector, const Matrix& matrix);
std::ostream& operator << (std::ostream& outputStream, const Matrix& matrix);
std::istream& operator >> (std::istream& inputStream, Matrix& matrix);
